#include "./stl_util_test.h"

TEST(Array, constructor_void) {

	// Arrange
	Array<int> *list1 = new Array<int>();

	// Assert
	EXPECT_TRUE( list1 != NULL );

};

TEST(Array, constructor_copy) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>( *list1 );

	// Assert
	EXPECT_TRUE( list1 != NULL );
	EXPECT_TRUE( list2 != NULL );

};

TEST(Array, at_throws_OutOfBoundsException) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	bool right_exception = false;

	// Act
	try {
		list1->at( 0 );
	}
	catch ( OutOfBoundsException ){
		right_exception = true;
	}
	catch ( ... ){
		right_exception = false;
	}

	// Assert
	EXPECT_TRUE( right_exception );

};

TEST(Array, insert) {

	// Arrange
	Array<int> *list1 = new Array<int>();

	// Act
	list1->insert(0);

	// Assert
	EXPECT_EQ( list1->at(0), 0 );

};

TEST(Array, size) {

	// Arrange
	Array<int> *list1 = new Array<int>();

	// Act
	// Assert
	EXPECT_EQ( list1->size(), 0 );
	list1->insert( 0 );
	EXPECT_EQ( list1->size(), 1 );
	list1->insert( 0 );
	EXPECT_EQ( list1->size(), 2 );

};

TEST(Array, operatorComma) {

	// Arrange
	Array<int> *list1 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;

	// Assert
	for( usint i = 0; i < 4; ++i )
		EXPECT_EQ( list1->at( i ), (int) i );

};

TEST(Array, operatorBrackets_usint) {

	// Arrange
	Array<int> *list1 = new Array<int>();

	// Act
	list1->insert( 1 );

	// Assert
	EXPECT_EQ( (*list1)[0], 1 );

	// Act
	(*list1)[0] = -1;

	// Assert
	EXPECT_EQ( (*list1)[0], -1 );

};

TEST(Array, operatorEqual_ArrayInt_and_ArrayInt_true) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2, 3;

	// Assert
	EXPECT_TRUE( (*list1) == (*list2) );

};

TEST(Array, operatorEqual_ArrayInt_and_ArrayInt_false_size) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2;

	// Assert
	EXPECT_FALSE( (*list1) == (*list2) );

};

TEST(Array, operatorEqual_ArrayInt_and_ArrayInt_false_content) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2, 4;

	// Assert
	EXPECT_FALSE( (*list1) == (*list2) );

};

TEST(Array, operatorNotEqual_ArrayInt_and_ArrayInt_false) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2, 3;

	// Assert
	EXPECT_FALSE( (*list1) != (*list2) );

};

TEST(Array, operatorNotEqual_ArrayInt_and_ArrayInt_true_size) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2;

	// Assert
	EXPECT_TRUE( (*list1) != (*list2) );

};

TEST(Array, operatorNotEqual_true_ArrayInt_and_ArrayInt_content) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 1, 2, 4;

	// Assert
	EXPECT_TRUE( (*list1) != (*list2) );

};

// having an operator == defined I can use EXPECT_EQ
TEST(Array, ArrayInt_iterator) {

	// Arrange
	Array<int> *list1 = new Array<int>();
	Array<int> *list2 = new Array<int>();

	// Act
	(*list1), 0, 1, 2, 3;
	(*list2), 0, 2, 4, 6;

	for( Array<int>::Iter i = list1->begin(); i != list1->end(); ++i )
		(*i) *= 2;

	// Assert
	EXPECT_EQ( (*list1), (*list2) );

};

TEST(Array, operatorAttribution_ArrayInt_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 1, 2, 3;
	Array<int> list2, final_list2;
	list2, 1, 2, 3; final_list2.copy( list2 );
	Array<int> expected;
	expected, 1, 2, 3;

	// Act
	Array<int> actual = ( list1 = list2 );

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( list2, final_list2 );
	EXPECT_EQ( expected, actual );
};

TEST(Array, operatorAddition_ArrayInt_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1.copy( list1 );
	Array<int> list2, final_list2;
	list2, 1, 2, 3; final_list2.copy( list2 );
	Array<int> expected;
	expected, 0, 1, 2, 3, 1, 2, 3;

	// Act
	Array<int> actual = list1 + list2;

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( list2, final_list2 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAdditionAndAttribution_ArrayInt_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3, 1, 2, 3, -1, -2;
	Array<int> list2, final_list2;
	list2, 1, 2, 3; final_list2.copy( list2 );
	Array<int> list3, final_list3;
	list3, -1, -2; final_list3.copy( list3 );
	Array<int> expected;
	expected, 0, 1, 2, 3, 1, 2, 3, -1, -2;

	// Act
	Array<int> actual = ( ( list1 += list2 ) += list3 );

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( list2, final_list2 );
	EXPECT_EQ( list3, final_list3 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, toS) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string expected = "[ 0 1 2 3 ]";

	// Act
	string actual = list1.toS();

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAddition_ArrayInt_and_string) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string str1 = " List", final_str1 = " List";
	string expected = "[ 0 1 2 3 ] List";

	// Act
	string actual = list1 + str1;

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAddition_string_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string str1 = "List ", final_str1 = "List ";
	string expected = "List [ 0 1 2 3 ]";

	// Act
	string actual = str1 + list1;

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAdditionAndAttribution_string_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string str1 = "List ", final_str1 = "List [ 0 1 2 3 ]";
	string expected = "List [ 0 1 2 3 ]";

	// Act
	string actual = ( str1 += list1 );

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAddition_ArrayInt_and_charPtr) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string expected = "[ 0 1 2 3 ] List";

	// Act
	string actual = list1 + " List";

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, operatorAddition_charPtr_and_ArrayInt) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	string expected = "List [ 0 1 2 3 ]";

	// Act
	string actual = "List " + list1;

	// Assert
	EXPECT_EQ( list1, final_list1 );
	EXPECT_EQ( expected, actual );

};

TEST(Array, AsPointerArray) {

	// Arrange
	Array<int> list1, final_list1;
	list1, 0, 1, 2, 3; final_list1, 0, 1, 2, 3;
	int *expected = (int*) malloc( 4*sizeof(int) );
	if( expected == NULL )
		throw MemoryException("Error while allocating memory for int array.", sizeof(int), 4 );

	expected[0] = 0; expected[1] = 1; expected[2] = 2; expected[3] = 3;

	// Act
	int *actual = list1.AsPointerArray();

	// Assert
	EXPECT_EQ( list1, final_list1 );
	for( usint i = 0; i < 4; ++i )
		EXPECT_EQ( expected[i], actual[i] );

};

// Remember ctrl+shift+insert = change ctrl+v to previous results
